/*
	Copyright (C) 2011 Daniel C. Dennison (dandennison84@gmail.com).  All rights reserved.
	This file is licensed under the EPL 1.0 (Eclipse Public License 1.0)
	A copy of the license can be found at http://www.eclipse.org/legal/epl-v10.html
*/

package com.gmail.dandennison84.accounting

import org.junit.Before
import org.junit.Test

class ChartOfAccountsBuilderTest {
	String prefix = 'src/test/groovy/' + ChartOfAccountsBuilderTest.package.name.replace('.', '/') + '/ChartOfAccountsTest-'
	List<Account> coa
	Account cashAccount, loanAccount, investments, contraInvestments, shortTermLiabilities, equipment, accumulatedDepreciation
	String expected, result

	@Before	
	void before() {
		def coab = new ChartOfAccountsBuilder()
		coab.groups(accountType:AccountType.ASSETS, balanceType:BalanceType.DEBIT, closingType:ClosingType.PERMANENT, cashFlowStatementType:CashFlowStatementType.OPERATING_ACTIVITIES) {
			currentAssets {
				account(name:'Cash')
			}
			account(name:'Investments', contraName:'Contra Investments') {
				properties {
					par 1.0
					shares 1000
				}
			}
			contra(name:'Contra Investments', balanceType:BalanceType.CREDIT, closingType:ClosingType.TEMPORARY)
			fixedAssets {
				account(name:'Equipment') {
					contra(name:'Accumulated Depreciation', balanceType:BalanceType.CREDIT, closingType:ClosingType.TEMPORARY)
				}
			}
		}
		coab.groups(accountType:AccountType.LIABILITIES, balanceType:BalanceType.CREDIT, closingType:ClosingType.PERMANENT,
			cashFlowStatementType:CashFlowStatementType.OPERATING_ACTIVITIES) {
			currentLiabilities {
				account {
					name 'Loan'
				}
				account(name:'Short-term Liabilities')
			}
		}
		coa = coab.accounts
		cashAccount = findAccount(coa, 'Cash')
		assert cashAccount
		investments = findAccount(coa, 'Investments')
		assert investments
		contraInvestments = findAccount(coa, 'Contra Investments')
		assert contraInvestments
		equipment = findAccount(coa, 'Equipment')
		assert equipment
		accumulatedDepreciation = findAccount(coa, 'Accumulated Depreciation')
		assert accumulatedDepreciation
		loanAccount = findAccount(coa, 'Loan')
		assert loanAccount
		shortTermLiabilities = findAccount(coa, 'Short-term Liabilities')
		assert shortTermLiabilities
	}

	@Test
	void testAccountProperties() {
		assert investments.properties.size() == 2
		assert investments.properties['par'] == 1.0
		assert investments.properties['shares'] == 1000
	}

	@Test
	void testAccountList() {
		assert 7 == coa.size
	}

	@Test
	void testGetAccounts() {
		assert [cashAccount, investments, contraInvestments, equipment,
			accumulatedDepreciation, loanAccount, shortTermLiabilities] == coa
	}
	
	@Test
	void testChartOfAccountsForReporting() {
		def coab = new ChartOfAccountsBuilder()
		coab.groups(accountType:AccountType.ASSETS, balanceType:BalanceType.DEBIT, closingType:ClosingType.PERMANENT,
			cashFlowStatementType:CashFlowStatementType.OPERATING_ACTIVITIES) {
			currentAssets {
				account(name:'Cash')
			}
			fixedAssets {
				account(name:'Equipment')
			}
		}
		coab.groups(accountType:AccountType.LIABILITIES, balanceType:BalanceType.CREDIT, closingType:ClosingType.PERMANENT,
			cashFlowStatementType:CashFlowStatementType.OPERATING_ACTIVITIES) {
			currentLiabilities {
				account(name:'Accounts Payable')
			}
			longTermLiabilities {
				account(name:'Long Term Loans')
			}
		}
		coab.groups(accountType:AccountType.EQUITY, balanceType:BalanceType.CREDIT, closingType:ClosingType.PERMANENT,
			cashFlowStatementType:CashFlowStatementType.OPERATING_ACTIVITIES) {
			account(name:'Capital')
			account(name:'Common Stock')
			account(name:'Retained Earnings')
			account(name:'Dividends', contra:true)
		}
		coab.groups(accountType:AccountType.REVENUE, balanceType:BalanceType.CREDIT, closingType:ClosingType.TEMPORARY,
			cashFlowStatementType:CashFlowStatementType.OPERATING_ACTIVITIES) {
			operatingRevenue {
				account(name:'Sales')
			}
			nonOperatingRevenue {
				account(name:'Interest Income')
			}
		}
		coab.groups(accountType:AccountType.EXPENSES, balanceType:BalanceType.DEBIT, closingType:ClosingType.TEMPORARY,
			cashFlowStatementType:CashFlowStatementType.OPERATING_ACTIVITIES) {
			operatingExpenses {
				account(name:'Labor Costs')
				account(name:'Advertising Costs')
			}
		}
		coa = coab.accounts

		Account cashAccount = findAccount(coa, 'Cash')
		Account equipmentAccount = findAccount(coa, 'Equipment')
		Account accountsPayableAccount = findAccount(coa, 'Accounts Payable')
		Account longTermLoansAccount = findAccount(coa, 'Long Term Loans')
		Account capitalAccount = findAccount(coa, 'Capital')
		Account commonStock = findAccount(coa, 'Common Stock')
		Account retainedEarningsAccount = findAccount(coa, 'Retained Earnings')
		Account dividendAccount = findAccount(coa, 'Dividends')
		Account salesAccount = findAccount(coa, 'Sales')
		Account interestIncomeAccount = findAccount(coa, 'Interest Income')
		Account laborCostAccount = findAccount(coa, 'Labor Costs')
		Account advertisingExpenseAccount = findAccount(coa, 'Advertising Costs')

		assert [cashAccount, equipmentAccount, accountsPayableAccount, longTermLoansAccount,
			capitalAccount, commonStock, retainedEarningsAccount, dividendAccount, salesAccount,
			interestIncomeAccount, laborCostAccount, advertisingExpenseAccount] == coa
	}

	private Account findAccount(List<Account> coa, String name) {
		coa.find {it.name == name}
	}
}
